package com.aabte.lota.auth.common.util;

import com.aabte.commons.basic.util.ExceptionUtils;
import com.aabte.commons.json.JSONUtils;
import com.aabte.lota.auth.auth.shiro.JwtAuthenticationFilter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.Enumeration;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author Daniel
 * @version 1.0
 * @date 2020/4/5
 */
@Slf4j
public class ServletUtils {

  public static String getServletPath() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getServletPath();
  }

  public static String getContextPath() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getContextPath();
  }

  public static String getMethod() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getMethod();
  }

  public static String getQueryString() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getQueryString();
  }

  public static String getCharacterEncoding() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getCharacterEncoding();
  }

  public static String getContentType() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getContentType();
  }

  public static String getRequestURI() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getRequestURI();
  }

  public static String getParameter(String name) {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getParameter(name);
  }

  public static String getHeader(String name) {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getHeader(name);
  }

  public static Object getAttribute(String name) {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getAttribute(name);
  }

  public static StringBuffer getRequestURL() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getRequestURL();
  }

  public static String getRemoteAddr() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getRemoteAddr();
  }

  public static String getRemoteHost() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getRemoteHost();
  }

  public static Integer getRemotePort() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getRemotePort();
  }

  public static Enumeration<String> getAttributeNames() {
    HttpServletRequest httpServletRequest = getHttpServletRequest();
    return httpServletRequest.getAttributeNames();
  }

  public static HttpServletRequest getHttpServletRequest() {
    ServletRequestAttributes servletRequestAttributes =
        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    assert servletRequestAttributes != null;
    return servletRequestAttributes.getRequest();
  }

  public static HttpServletResponse getHttpServletResponse() {
    ServletRequestAttributes servletRequestAttributes =
        (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    assert servletRequestAttributes != null;
    return servletRequestAttributes.getResponse();
  }

  public static String getJwtToken() {
    return getHttpServletRequest().getHeader(JwtAuthenticationFilter.HEADER_NAME_TOKEN);
  }

  public static void writeBody(Object result) {
    HttpServletResponse httpServletResponse = getHttpServletResponse();
    String json = JSONUtils.toJson(result);
    try {
      httpServletResponse.getOutputStream().write(json.getBytes(StandardCharsets.UTF_8));
      httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
      httpServletResponse.setCharacterEncoding(StandardCharsets.UTF_8.name());
    } catch (IOException e) {
      log.warn("write body failed. ex: {}", ExceptionUtils.getErrorStack(e));
    }
  }

  public static void setResponseHeader(String name, Object value) {
    HttpServletResponse httpServletResponse = getHttpServletResponse();
    if (value instanceof Integer) {
      httpServletResponse.setIntHeader(name, (Integer) value);
    } else if (value instanceof Date) {
      httpServletResponse.setDateHeader(name, ((Date) value).getTime());
    } else if (value instanceof LocalDateTime) {
      long epochMilli =
          ((LocalDateTime) value).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
      httpServletResponse.setDateHeader(name, epochMilli);
    } else {
      httpServletResponse.setHeader(name, value.toString());
    }
  }

  public static void setResponseHeaders(Map<String, Object> headers) {
    HttpServletResponse httpServletResponse = getHttpServletResponse();
    for (Entry<String, Object> entry : headers.entrySet()) {
      setResponseHeader(entry.getKey(), entry.getValue());
    }
  }
}
